/*
 * Author: vdaras
 */

#include "ScrollableText.h"

namespace gui
{

ScrollableText::ScrollableText()
{
    m_lowIndex = 0;
    m_highIndex = 1;
}

ScrollableText::ScrollableText(const std::string &text)
:
Text(text)
{
    m_lowIndex = 0;
    m_highIndex = 1;
}

ScrollableText::~ScrollableText()
{
}


/**
 * Returns viewable part of the current row.
 *
 * @param a string containing the viewble text of the current row.
 */

std::string ScrollableText::getViewableRow() const
{
    if(m_rows.empty())
    {
        return "";
    }

    const std::string &currentRow = m_rows[GetCursorRow()];

    return currentRow.substr(m_lowIndex, m_highIndex - m_lowIndex);
}

/**
 * This method moves the cursor right. The extra functionality, besides the plain
 * Text's, is that if the cursor is pointing to a character higher than the high
 * index (maximum viewable index), then the low and high indices are moved one
 * spot to the right
 */

void ScrollableText::MoveCursorRight()
{
    //make standard cursor movement
    Text::MoveCursorRight();
    //if the current column of the cursor is greater than the high index
    if(GetCursorColumn() > m_highIndex)
    {
        //move low and high indices a spot to the right
        ++m_lowIndex;
        ++m_highIndex;
    }
}

/**
 * This method moves the cursor left. The extra functionality, besides the plain
 * Text's, is that if the cursor is pointing to a character lower than the low
 * index (maximum viewable index), then the low and high indices are moved one
 * spot to the right
 */

void ScrollableText::MoveCursorLeft()
{
    //make standard cursor movement
    Text::MoveCursorLeft();
    //if the current column of the cursor is lower than the low index
    if(GetCursorColumn() < m_lowIndex)
    {
        //move low and high indices a spot to the left
        --m_lowIndex;
        --m_highIndex;
    }
}

/**
 * This routine maps the cursor's X based on the scrolled text.
 *
 * @param fnt: font used to measure sizes
 * @return cursor's x position on screen.
 */

int ScrollableText::GetCursorX(sdl::Font *fnt) const
{
    int ret = 0;

    //if there exist text and the current length of the row has surpassed the maximum viewable characters
    if(!m_rows.empty())
    {
        //get width of text from the lowest viewable index to the cursor's current column
        const std::string &currentRow = m_rows[m_cursorRow];
        int textWidth, textHeight;
        fnt->TextSize(currentRow.substr(m_lowIndex, m_cursorColumn - m_lowIndex), textWidth, textHeight);
        //set result as the found width
        ret = textWidth + 1;
    }

    return ret;
}


/**
 * This routine translates a point to cursor indices in text. The problem with
 * scrollable text is that these indices are calculated differently than regular
 * text since these coordinates must be translated depending on the viewed area
 * of the text.
 *
 * @param fnt: font used to measure sizes
 */

void ScrollableText::SetCursorFromPoint(int pointX, int pointY, sdl::Font *fnt)
{    
    int adjustedPointX = pointX;
    //if there exist's text
    if(!m_rows.empty())
    {
		int txtWidth, txtHeight;
        std::string &currentRow = m_rows[m_cursorRow];
        //get width of text till the low index
        fnt->TextSize(currentRow.substr(0, m_lowIndex), txtWidth, txtHeight);
        //adjust point x coordinate
        adjustedPointX += txtWidth;
    }

    Text::SetCursorFromPoint(adjustedPointX, pointY, fnt);
}


/**
 * Increases the high index of the scrollable text.
 */

void ScrollableText::IncreaseHigh()
{
    if(m_highIndex <= m_rows[m_cursorRow].length())
    {
        ++m_highIndex;
    }
}


/**
 * Descreases the high index of the scrollable text.
 */

void ScrollableText::DecreaseHigh()
{
    if(m_highIndex - 1 > m_lowIndex)
    {
        --m_highIndex;
    }
}


/**
 * Increases the low index of the scrollable text.
 */

void ScrollableText::IncreaseLow()
{
    if(m_lowIndex + 1 < m_highIndex)
    {
        ++m_lowIndex;
    }
}


/**
 * Decrease the low index of the scrollable text.
 */

void ScrollableText::DecreaseLow()
{
    if(m_lowIndex - 1 >= 0)
    {
        --m_lowIndex;
    }
}



};
